#include "Plugin.h"
#include <cstdio>
#include <cstdlib>

char * Data;

unsigned long long Length;

unsigned long long Pointer;

unsigned long long start_ptr;

unsigned long long end_ptr;

const char * prefixSurport() {
    return "wav";
}

bool Checking(void * pData, unsigned long long length) {

    char * pData1 = (char *) pData;

    if (pData1[0] != 'R' || pData1[1] != 'I' || pData1[2] != 'F' || pData1[3]
            != 'F')
        return false;

    if (pData1[8] != 'W' || pData1[9] != 'A' || pData1[10] != 'V' || pData1[11]
            != 'E')
        return false;

    if (pData1[12] != 'f' || pData1[13] != 'm' || pData1[14] != 't'
            || pData1[15] != ' ')
        return false;

    if ((*(unsigned short *) (pData1 + 20)) != 0x0001)
        return false;

    Data = pData1;

    Length = length;

    Pointer = 30 + *(unsigned *) (Data + 16);

    return true;

}

void getStatus(unsigned * pFormat, unsigned * pChannels, unsigned * pRate) {

    *pChannels = (*(unsigned short *) (Data + 22));

    *pRate = (*(unsigned *) (Data + 24));

    *pFormat = (*(unsigned short *) (Data + 34));

}

bool Decoding(void * pTarget, size_t length, size_t * ReadSize) {

    if (Pointer >= end_ptr) return false;

    if (Pointer + length >= end_ptr) {

        memcpy(pTarget, Data + Pointer, end_ptr - Pointer);

        *ReadSize = Length - Pointer;

        Pointer += Length - Pointer;


    } else {

        memcpy(pTarget, Data + Pointer, length);

        *ReadSize = length;

        Pointer += length;

    }

    return true;

}

bool SetTrack(int Min, int Second, int Frame, int EndMin, int EndSecond,
        int EndFrame) {

    unsigned format;

    unsigned channels;

    unsigned rate;

    unsigned long long start = 60 * Min + Second + Frame / 75;

    unsigned long long end = 60 * EndMin + EndSecond + EndFrame / 75;

    getStatus(&format, &channels, &rate);

    start_ptr = (channels * format * rate) * start / 8;

    if (EndMin == -1 && EndSecond == -1 && EndFrame == -1)

        end_ptr = Length;

    else

        end_ptr = (channels * format * rate) * end / 8;

    Pointer = 30 + *(unsigned *) (Data + 16) + start_ptr;
    
    if( end_ptr > Length ) end_ptr = Length;

    return true;

}

bool Seek( int Min, int Second, int Frame ){
    unsigned format;

    unsigned channels;

    unsigned rate;

    int start = 60 * Min + Second + Frame / 75;

    getStatus(&format, &channels, &rate);
    
    unsigned long long ptr = (channels * format * rate) * start / 8;
    
    if( ptr >= end_ptr ) return false;
    
    Pointer = 30 + *(unsigned *) (Data + 16) + ptr;
    
    return true;
    
}

void getTotalTime( int * pMin, int * pSecond, int * pFrame ){
    
    unsigned format;

    unsigned channels;

    unsigned rate;
    
    getStatus(&format, &channels, &rate);
    
    unsigned long long soundLength = Length - 30 - *(unsigned*)(Data+16);
    
    unsigned long long seconds = soundLength * 8 / (channels * format * rate);
    
    *pMin = seconds / 60;
    
    seconds -= *pMin * 60;
    
    *pSecond = seconds;
    
    *pFrame = 0;
    
}